import { AssetManager, assetManager, AudioClip, AudioSource, director, Node, resources } from "cc";

export default class SoundManager{
    private static _ins:SoundManager=null;
    public static get ins():SoundManager{
        if(!this._ins)this._ins=new SoundManager();
        return this._ins;
    }
    private _audioSource: AudioSource;
    private _shotAudioSource:AudioSource;
    private mMute:boolean=false;
    private mSoundBound:AssetManager.Bundle;
    private mIsBundleLoading:boolean=false;
    constructor(){
        let audioMgr = new Node();
        audioMgr.name = '__audioMgr__';

        //@en add to the scene.
        //@zh 添加节点到场景
        director.getScene().addChild(audioMgr);

        //@en make it as a persistent node, so it won't be destroied when scene change.
        //@zh 标记为常驻节点，这样场景切换的时候就不会被销毁了
        director.addPersistRootNode(audioMgr);

        //@en add AudioSource componrnt to play audios.
        //@zh 添加 AudioSource 组件，用于播放音频。
        this._audioSource = audioMgr.addComponent(AudioSource);

        let tshotAudio = new Node();
        tshotAudio.name="__showaudio__";
        director.getScene().addChild(tshotAudio);
        director.addPersistRootNode(tshotAudio);
        this._shotAudioSource = tshotAudio.addComponent(AudioSource);
    }

    public get audioSource() {
        return this._audioSource;
    }

    /**
     * @en
     * play short audio, such as strikes,explosions
     * @zh
     * 播放短音频,比如 打击音效，爆炸音效等
     * @param sound clip or url for the audio
     * @param volume 
     */
    playOneShot(sound: AudioClip | string, volume: number = 1.0) {
        if(this.mMute)return;
        if (sound instanceof AudioClip) {
            this._shotAudioSource.playOneShot(sound, volume);
        }
        else {
            if(this.mSoundBound){
                this.mSoundBound.load(sound,(err,_sound)=>{
                    let tsound:AudioClip = _sound as AudioClip;
                    if(tsound)this._shotAudioSource.playOneShot(tsound, volume);
                });
            }else{
                if(this.mIsBundleLoading)return;
                let tslef = this;
                this.mIsBundleLoading=true;
                assetManager.loadBundle("assets/sound",(err,bound:AssetManager.Bundle)=>{
                    if(err)return;
                    tslef.mSoundBound=bound;
                    tslef.mSoundBound.load(sound,(err,sound)=>{
                        let tsound:AudioClip = sound as AudioClip;
                        if(tsound){
                            tslef._shotAudioSource.playOneShot(tsound, volume);
                        }
                    });
                });
            }
        }
    }

    /**
     * @en
     * play long audio, such as the bg music
     * @zh
     * 播放长音频，比如 背景音乐
     * @param sound clip or url for the sound
     * @param volume 
     */
    play(sound: AudioClip | string, volume: number = 1.0) {
        if(this.mMute)return;
        if (sound instanceof AudioClip) {
            this._audioSource.stop();
            this._audioSource.clip = sound;
            this._audioSource.play();
            this.audioSource.volume = volume;
        }
        else {
            if(this.mSoundBound){
                this.mSoundBound.load(sound,(err,_sound)=>{
                    let tsound:AudioClip = _sound as AudioClip;
                    if(tsound){
                        this._audioSource.clip = tsound;
                        this._audioSource.loop=true;
                        this._audioSource.play();
                    }
                });
            }else{
                if(this.mIsBundleLoading)return;
                let tslef = this;
                this.mIsBundleLoading=true;
                assetManager.loadBundle("assets/sound",(err,bound:AssetManager.Bundle)=>{
                    if(err)return;
                    tslef.mSoundBound=bound;
                    tslef.mSoundBound.load(sound,(err,sound)=>{
                        let tsound:AudioClip = sound as AudioClip;
                        if(tsound){
                            tslef._audioSource.clip = tsound;
                            tslef._audioSource.loop=true;
                            tslef._audioSource.play();
                        }
                    });
                });
            }
        }
    }

    /**
     * stop the audio play
     */
    stop() {
        this._audioSource.stop();
    }

    /**
     * pause the audio play
     */
    pause() {
        this._audioSource.pause();
    }

    /**
     * resume the audio play
     */
    resume(){
        this._audioSource.play();
    }

    public setMute(mute:boolean,resume:boolean=false){
        this.mMute=mute;
        if(this.mMute)this.stop();
        else {
            if(resume)this.resume();
        }
    }

    public get mute(){
        return this.mMute;
    }
}